﻿// Copyright 2008 Benjamin Jenks 
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may 
// not use this file except in compliance with the License. You may obtain 
// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 
//
// Unless required by applicable law or agreed to in writing, software 
// distributed under the License is distributed on an "AS IS" BASIS, 
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
// See the License for the specific language governing permissions and 
// limitations under the License. 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;

using Newtonsoft.Json.Linq;

namespace iTunesAlbumArtFetcher.Core
{
    public class GImageSearch
    {
        public class SearchResults {
            public string Query { get; set; }
            public Cursor Cursor { get; set; }
            public List<Image> Images { get; set; }
        }

        public class Page {
            public int Start { get; set; }
            public string Label  { get; set; }
        }

        public class Cursor {
            public List<Page> Pages { get; set; }
            public int CurrentPageIndex { get; set; }
            public int EstimatedResultCount { get; set; }
            public string MoreResultsUrl { get; set; }

            public int NextOffset { 
                get { return this.Pages[ this.CurrentPageIndex + 1 ].Start; } 
            }
            public int PrevOffset {
                get { return this.Pages[ this.CurrentPageIndex - 1 ].Start; }
            }
        }

        public class Image {
            public string Name { get; set; } 
            public string OriginalUrl { get; set; } 
            public string ThumbUrl { get; set; }
            public string Description { get; set; }
            public int Height { get; set; }
            public int Width { get; set; }
            public int ThumbHeight { get; set; }
            public int ThumbWidth { get; set; }
        }

        public SearchResults Query(string query) {
            return this.Query( query, 0 );
        }

        private SearchResults Query(string query, int offset) {
            string data= this.Request( query, offset );
            return this.Parse( query, data );
        }

        public SearchResults NextPage(SearchResults results) {
            return this.Query( results.Query, results.Cursor.NextOffset );
        }

        private string Request(string query, int offset)
        {
            WebClient client = new WebClient();

            // set the referer header to be polite to google
            client.Headers["Referer"] = "iTunesAlbumArtFetcher - jenksb@gmail.com";

            // set the request parameters
            client.QueryString["v"] = "1.0";
            client.QueryString["q"] = query.Replace( "/", " " );
            client.QueryString["rsz"] = "large";
            client.QueryString["as_filetype"] = "jpg";
            client.QueryString["start"]= offset.ToString();

            // make the request
            return client.DownloadString("http://ajax.googleapis.com/ajax/services/search/images");
        }

        private SearchResults Parse(string query, string json) {
            JObject obj= JObject.Parse(json);
            
            // read in the image results
            JArray results= obj[ "responseData" ][ "results" ] as JArray;
            List<Image> images= (
                from token in obj[ "responseData" ][ "results" ]
                select new Image {
                    Name= token["titleNoFormatting"].Value<string>(),
                    Description = token["contentNoFormatting"].Value<string>(),
                    OriginalUrl= token["url"].Value<string>(),
                    Height= token["height"].Value<int>(),
                    Width= token["width"].Value<int>(),
                    ThumbUrl= token["tbUrl"].Value<string>(),
                    ThumbHeight= token["tbHeight"].Value<int>(),
                    ThumbWidth= token["tbWidth"].Value<int>()
                }
            ).ToList<Image>();

            Cursor cursor= null;
            try { // to parse in tnhe token data
                JToken cursorToken= obj[ "responseData" ][ "cursor" ];
                cursor= new Cursor {
                    EstimatedResultCount= cursorToken[ "estimatedResultCount" ].Value<int>(),
                    CurrentPageIndex= cursorToken[ "currentPageIndex" ].Value<int>(),
                    MoreResultsUrl= cursorToken[ "moreResultsUrl" ].Value<string>(),
                    Pages= (
                        from p in cursorToken[ "pages" ]
                        select new Page{ 
                            Label= p[ "label" ].Value<string>(),
                            Start= p[ "start" ].Value<int>()
                        }
                    ).ToList<Page>()
                };
            } catch (Exception) {
                cursor= new Cursor { 
                    CurrentPageIndex= 0, 
                    EstimatedResultCount= 0, 
                    MoreResultsUrl= "", 
                    Pages= new List<Page>()
                };
            }

            return new SearchResults {
                Query= query,
                Cursor= cursor,
                Images= images
            };
        }
    }
}